package com.ai.tool;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.Reader;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import com.alibaba.fastjson.JSONObject;

public class FileUtil {

	public static String getParentPath(String path) {
		return getParentPath(path, "/", 1);
	}

	public static String getParentPath(String path, int depth) {
		return getParentPath(path, "/", depth);
	}

	public static String getParentPath(String path, String fileSeparator, int depth) {
		for (int i = 0; i < depth; i++) {
			path = path.substring(0, path.lastIndexOf(fileSeparator));
		}
		return path;
	}

	public static void recurCreateFolder(String path) {
		File file = new File(path);
		if (file.getParentFile().exists()) {
			file.mkdir();
		} else {
			recurCreateFolder(file.getParentFile().getPath());
			file.mkdir();
		}
	}

	private static void copyFile(String srcPath, String desPath) {
		try {
			FileInputStream in = new FileInputStream(srcPath);
			FileOutputStream out = new FileOutputStream(desPath);
			byte[] bt = new byte[1024];
			int count;
			while ((count = in.read(bt)) > 0) {
				out.write(bt, 0, count);
			}
			in.close();
			out.close();
		} catch (IOException ex) {
			throw new RuntimeException(String.format("鎷疯礉鏂囦欢鍑洪敊,婧愭枃浠讹細%s, 鐩爣鏂囦欢锛�%s", srcPath, desPath), ex);
		}
	}

	public static void copyAndReplaceFile(String srcPath, String desPath) {
		srcPath = separatorReplace(srcPath);
		desPath = separatorReplace(desPath);
		File srcFile = new File(srcPath);
		if (!srcFile.isFile()) {
			throw new RuntimeException("source file not found!");
		}
		copyFile(srcPath, desPath);
	}

	public static void copyAndNotReplaceFile(String srcPath, String desPath) throws Exception {
		srcPath = separatorReplace(srcPath);
		desPath = separatorReplace(desPath);
		File srcFile = new File(srcPath);
		File desFile = new File(desPath);
		if (!srcFile.isFile()) {
			throw new Exception("source file not found!");
		}
		if (desFile.isFile()) {
			return;
		}
		copyFile(srcPath, desPath);
	}

	public static void copyAndNotReplace(String srcPath, String desPath) throws Exception {
		srcPath = separatorReplace(srcPath);
		desPath = separatorReplace(desPath);
		File srcFile = new File(srcPath);
		File desFile = new File(desPath);
		if (!srcFile.isFile()) {
			throw new Exception("source file not found!");
		}
		if (desFile.isFile() && srcFile.length() == desFile.length()) {
			return;
		}
		copyFile(srcPath, desPath);
	}

	public static void moveAndReplaceFile(String srcPath, String desPath) throws Exception {
		srcPath = separatorReplace(srcPath);
		desPath = separatorReplace(desPath);
		copyAndReplaceFile(srcPath, desPath);
		deleteFile(srcPath);
	}

	public static void moveAndNotReplaceFile(String srcPath, String desPath) throws Exception {
		srcPath = separatorReplace(srcPath);
		desPath = separatorReplace(desPath);
		copyAndNotReplaceFile(srcPath, desPath);
		deleteFile(srcPath);
	}

	public static void copyAndMergerFolder(String srcPath, String desPath) throws Exception {
		srcPath = separatorReplace(srcPath);
		desPath = separatorReplace(desPath);
		File folder = getFolder(srcPath);
		createFolder(desPath);
		File[] files = folder.listFiles();
		for (File file : files) {
			String src = file.getAbsolutePath();
			String des = desPath + File.separator + file.getName();
			if (file.isFile()) {
				copyAndNotReplaceFile(src, des);
			} else if (file.isDirectory()) {
				copyAndMergerFolder(src, des);
			}
		}
	}

	public static void copyAndReplaceFolder(String srcPath, String desPath) throws Exception {
		srcPath = separatorReplace(srcPath);
		desPath = separatorReplace(desPath);
		File folder = getFolder(srcPath);
		createNewFolder(desPath);
		File[] files = folder.listFiles();
		for (File file : files) {
			String src = file.getAbsolutePath();
			String des = desPath + File.separator + file.getName();
			if (file.isFile()) {
				copyAndReplaceFile(src, des);
			} else if (file.isDirectory()) {
				copyAndReplaceFolder(src, des);
			}
		}
	}

	public static void moveAndMergerFolder(String srcPath, String desPath) throws Exception {
		srcPath = separatorReplace(srcPath);
		desPath = separatorReplace(desPath);
		copyAndMergerFolder(srcPath, desPath);
		deleteFolder(srcPath);
	}

	public static void moveAndReplaceFolder(String srcPath, String desPath) throws Exception {
		srcPath = separatorReplace(srcPath);
		desPath = separatorReplace(desPath);
		copyAndReplaceFolder(srcPath, desPath);
		deleteFolder(srcPath);
	}

	public static void createFolder(String path) {
		path = separatorReplace(path);
		File folder = new File(path);
		if (folder.isDirectory()) {
			return;
		} else if (folder.isFile()) {
			deleteFile(path);
		}
		folder.mkdirs();
	}

	public static void createNewFolder(String path) {
		path = separatorReplace(path);
		File folder = new File(path);
		if (folder.isDirectory()) {
			deleteFolder(path);
		} else if (folder.isFile()) {
			deleteFile(path);
		}
		folder.mkdirs();
	}

	public static File createFile(String path) {
		path = separatorReplace(path);
		File file = new File(path);
		if (file.isFile()) {
			return file;
		} else if (file.isDirectory()) {
			deleteFolder(path);
		}
		return createFile(file);
	}

	public static File createNewFile(String path) throws Exception {
		path = separatorReplace(path);
		File file = new File(path);
		if (file.isFile()) {
			deleteFile(path);
		} else if (file.isDirectory()) {
			deleteFolder(path);
		}
		return createFile(file);
	}

	public static String separatorReplace(String path) {
		return path.replace("\\", "/");
	}

	public static File createFile(File file) {
		createParentFolder(file);
		try {
			if (!file.createNewFile()) {
				throw new RuntimeException("create file failure!");
			}
		} catch (IOException e) {
			e.printStackTrace();
			throw new RuntimeException("鍒涘缓鏂囦欢澶辫触create file failure!");
		}
		return file;
	}

	public static boolean createFile(String absolutePath, byte[] buf) throws IOException {
		FileOutputStream fs = null;
		boolean bl = false;
		try {
			String filePath = absolutePath;
			File file = new File(filePath);
			createParentFolder(file);
			if (!file.exists()) {
				bl = file.createNewFile();
			}
			fs = new FileOutputStream(file);
			fs.write(buf);
		} catch (IOException e) {
			throw e;
		} finally {
			close(fs);
		}
		return bl;
	}

	public static void createParentFolder(File file) {
		if (!file.getParentFile().exists()) {
			if (!file.getParentFile().mkdirs()) {
				throw new RuntimeException("create parent directory failure!");
			}
		}
	}

	public static void deleteFile(String path) {
		path = separatorReplace(path);
		File file;
		try {
			file = getFile(path);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
			throw new RuntimeException("鏂囦欢娌℃壘鍒�:" + path);
		}
		if (!file.delete()) {
			throw new RuntimeException("鍒犻櫎鏂囦欢澶辫触");
		}
	}

	public static void deleteFile(String dir, String prefix, String suffix) throws Exception {
		dir = separatorReplace(dir);
		File directory = getFolder(dir);
		File[] files = directory.listFiles();
		for (File file : files) {
			if (file.isFile()) {
				String fileName = file.getName();
				if (fileName.startsWith(prefix) && fileName.endsWith(suffix)) {
					deleteFile(file.getAbsolutePath());
				}
			}
		}
	}

	public static void deleteFolder(String path) {
		path = separatorReplace(path);
		File folder = getFolder(path);
		File[] files = folder.listFiles();
		for (File file : files) {
			if (file.isDirectory()) {
				deleteFolder(file.getAbsolutePath());
			} else if (file.isFile()) {
				deleteFile(file.getAbsolutePath());
			}
		}
		folder.delete();
	}

	public static File searchFile(String dir, String fileName) throws FileNotFoundException {
		dir = separatorReplace(dir);
		File f = null;
		File folder = getFolder(dir);
		File[] files = folder.listFiles();
		for (File file : files) {
			if (file.isDirectory()) {
				f = searchFile(file.getAbsolutePath(), fileName);
				if (f != null) {
					break;
				}
			} else if (file.isFile()) {
				if (file.getName().equals(fileName)) {
					f = file;
					break;
				}
			}
		}
		return f;
	}

	public static String getFileType(String path) throws FileNotFoundException {
		path = separatorReplace(path);
		File file = getFile(path);
		String fileName = file.getName();
		String[] strs = fileName.split("\\.");
		if (strs.length < 2) {
			return "unknownType";
		}
		return strs[strs.length - 1];
	}

	public static long getFileSize(String path) throws FileNotFoundException {
		path = separatorReplace(path);
		File file = getFile(path);
		return file.length();
	}

	public static long getFolderSize(String path) throws FileNotFoundException {
		path = separatorReplace(path);
		long size = 0;
		File folder = getFolder(path);
		File[] files = folder.listFiles();
		for (File file : files) {
			if (file.isDirectory()) {
				size += getFolderSize(file.getAbsolutePath());
			} else if (file.isFile()) {
				size += file.length();
			}
		}
		return size;
	}

	public static File getFile(String path) throws FileNotFoundException {
		path = separatorReplace(path);
		File file = new File(path);
		if (!file.isFile()) {
			throw new FileNotFoundException("file not found!");
		}
		return file;
	}

	public static File getFolder(String path) {
		path = separatorReplace(path);
		File folder = new File(path);
		if (!folder.isDirectory()) {
			throw new RuntimeException(new FileNotFoundException("folder not found!"));
		}
		return folder;
	}

	public static Date getFileLastModified(String path) throws FileNotFoundException {
		path = separatorReplace(path);
		File file = getFile(path);
		return new Date(file.lastModified());
	}

	public static Date getFolderLastModified(String path) throws FileNotFoundException {
		path = separatorReplace(path);
		File folder = getFolder(path);
		return new Date(folder.lastModified());
	}

	public static void write(String fileName, String content) {
		File file = new File(fileName);
		try (FileWriter fw = new FileWriter(file, false)) {
			fw.write(content);
		} catch (IOException e) {
			throw new RuntimeException("鍐欐枃浠跺嚭閿欙細" + file.getName(), e);
		}
	}

	public static String read(String fileName) {
		return read(fileName, "UTF-8");
	}

	public static String read(String fileName, String charsetName) {
		File file = new File(fileName);
		return read(file, charsetName);
	}

	public static String read(File file, String charsetName) {
		StringBuilder sb = new StringBuilder();
		try (FileInputStream fis = new FileInputStream(file);
				InputStreamReader isr = new InputStreamReader(fis, charsetName);
				BufferedReader br = new BufferedReader(isr)) {

			String line = null;
			while ((line = br.readLine()) != null) {
				sb.append(line).append('\n');
			}
		} catch (IOException e) {
			e.printStackTrace();
			throw new RuntimeException("璇绘枃浠跺嚭閿欙細" + file.getName(), e);
		}
		return sb.toString();
	}

	public static List<File> getSubDirList(File fileRoot) {
		File[] files = fileRoot.listFiles();
		List<File> list = new ArrayList<File>();
		if (files != null) {
			for (File ff : files) {
				if (ff.isDirectory()) {
					list.add(ff);
				}
			}
		}
		return list;
	}

	public static List<File> getSubDirList(String folderPath) {
		File folder = new File(folderPath);
		return getSubDirList(folder);
	}

	public static List<String> getSubDirName(File fileRoot) {
		File[] files = fileRoot.listFiles();
		List<String> list = new ArrayList<String>();
		for (File ff : files) {
			if (ff.isDirectory()) {
				list.add(ff.getName());
			}
		}
		return list;
	}

	public static List<String> getSubDirPath(File fileRoot) {
		File[] files = fileRoot.listFiles();
		List<String> list = new ArrayList<String>();
		for (File ff : files) {
			if (ff.isDirectory()) {
				list.add(ff.getAbsolutePath());
			}
		}
		return list;
	}

	public static FilenameFilter filter(final String type) throws Exception {
		return new FilenameFilter() {
			public boolean accept(File file, String path) {
				String filename = new File(path).getName();
				return filename.indexOf(type) != -1;
			}
		};
	}

	public static File[] findSubDir(String path, String filterName) throws Exception {
		File ftpRoot = new File(path);
		File[] ftpFiles = ftpRoot.listFiles(FileUtil.filter(filterName));
		return ftpFiles;
	}

	public static List<File> getSubFileList(File fileRoot, String suffix) throws Exception {
		File[] files = null;
		if (suffix != null) {
			files = fileRoot.listFiles(FileUtil.filter(suffix));
		} else {
			files = fileRoot.listFiles();
		}
		List<File> list = new ArrayList<File>();
		for (File ff : files) {
			if (ff.isFile()) {
				list.add(ff);
			}
		}
		return list;
	}

	public static List<File> getRecursiveFileList(String fileRoot, String... suffix) throws Exception {
		return getRecursiveFileList(new File(fileRoot), suffix);
	}

	public static List<File> getRecursiveFileList(File fileRoot, String... suffix) throws Exception {
		List<File> list = new ArrayList<File>();
		showAllFiles(fileRoot, list, suffix);
		return list;
	}

	private static void showAllFiles(File dir, List<File> list, String... suffix) throws Exception {
		File[] fs = dir.listFiles();
		for (int i = 0; i < fs.length; i++) {
			if (fs[i].isDirectory()) {
				showAllFiles(fs[i], list, suffix);
			} else {
				String name = fs[i].getAbsolutePath().toString();
				boolean in = true;
				for (String s : suffix) {
					if (!name.contains(s)) {
						in = false;
					}
				}
				if (in) {
					list.add(fs[i]);
				}
			}
		}
	}

	public static List<File> getSubFileList(String folderPath) throws Exception {
		File folder = new File(folderPath);
		return getSubFileList(folder, null);
	}

	public static List<File> getSubFileList(String folderPath, String suffix) throws Exception {
		File folder = new File(folderPath);
		return getSubFileList(folder, suffix);
	}

	public static List<String> getSubFileName(File fileRoot) {
		File[] files = fileRoot.listFiles();
		List<String> list = new ArrayList<String>();
		for (File ff : files) {
			if (ff.isFile()) {
				list.add(ff.getName());
			}
		}
		return list;
	}

	public synchronized static void close(InputStream st) {
		try {
			if (st != null)
				st.close();
		} catch (IOException e) {
			// e.printStackTrace();
		}
	}

	public synchronized static void close(OutputStream st) {
		try {
			if (st != null)
				st.close();
		} catch (IOException e) {
			// e.printStackTrace();
		}
	}

	public synchronized static void close(Reader st) {
		try {
			if (st != null)
				st.close();
		} catch (IOException e) {
			// e.printStackTrace();
		}
	}

	/**
	 * @Title: close
	 * @Description: 鍏抽棴娴�
	 * @param @param st 璁惧畾鏂囦欢
	 * @return void 杩斿洖绫诲瀷
	 * @throws
	 */
	public synchronized static void close(Writer st) {
		try {
			if (st != null)
				st.close();
		} catch (IOException e) {
			// e.printStackTrace();
		}
	}

	/**
	 * @Title: stringToAscii
	 * @Description: 涓枃瀛楃杞珹scii
	 * @param @param value
	 * @param @return 璁惧畾鏂囦欢
	 * @return String 杩斿洖绫诲瀷
	 * @throws
	 */
	public static String stringToAscii(String value) {
		StringBuffer sbu = new StringBuffer();
		char[] chars = value.toCharArray();
		for (int i = 0; i < chars.length; i++) {
			if (i != chars.length - 1) {
				sbu.append((int) chars[i]).append(",");
			} else {
				sbu.append((int) chars[i]);
			}
		}
		return sbu.toString();
	}

	/**
	 * @Title: asciiToString
	 * @Description: ascii杞腑鏂�
	 * @param @param value
	 * @param @return 璁惧畾鏂囦欢
	 * @return String 杩斿洖绫诲瀷
	 * @throws
	 */
	public static String asciiToString(String value) {
		StringBuffer sbu = new StringBuffer();
		String[] chars = value.split(",");
		for (int i = 0; i < chars.length; i++) {
			sbu.append((char) Integer.parseInt(chars[i]));
		}
		return sbu.toString();
	}

	/**
	 * @Title: cutFile
	 * @Description: 鍚岀洏鍓垏鏂囦欢
	 * @param @param src
	 * @param @param dest
	 * @param @return 璁惧畾鏂囦欢
	 * @return boolean 杩斿洖绫诲瀷
	 * @throws
	 */
	public static boolean cutFile(File src, File dest) {
		return src.renameTo(dest);
	}

	/**
	 * @throws Exception 
	 * @throws Exception
	 * @Title: buildJson
	 * @Description: 閫掑綊骞惰繑鍥瀓son
	 * @param @param folderFile
	 * @param @return 璁惧畾鏂囦欢
	 * @return String 杩斿洖绫诲瀷
	 * @throws
	 */
	public static String buildJson(File folderFile) throws Exception  {
		JSONObject json = new JSONObject();
		json.put("level", 1);
		buildFolderJson(json, folderFile);
		String str = json.toJSONString();
		json.clear();
		return str;
	}

	public static void buildFolderJson(JSONObject root, File fileRoot) throws Exception {
		List<String> sub_files = new ArrayList<String>();
		List<JSONObject> sub_folders = new ArrayList<JSONObject>();
		File[] files = fileRoot.listFiles();
		if (files != null) {
			for (File ff : files) {
				if (ff.isFile()) {
					sub_files.add(ff.getName());
				} else {
					JSONObject j = new JSONObject();
					j.put("level", (int) root.get("level") + 1);
					sub_folders.add(j);
					buildFolderJson(j, ff);
				}
			}
		}
		root.put("name", fileRoot.getName());
		root.put("files", sub_files.toArray());
		root.put("folders", sub_folders);
	}

}